home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / othergnu / trmcap10.zoo / termcap.c < prev    next >
C/C++ Source or Header  |  1992-04-13  |  14KB  |  676 lines

  1. /* Work-alike for termcap, plus extra features.
  2.    Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* BUFSIZE is the initial size allocated for the buffer
  19.    for reading the termcap file.
  20.    It is not a limit.
  21.    Make it large normally for speed.
  22.    Make it variable when debugging, so can exercise
  23.    increasing the space dynamically.  */
  24.  
  25. #ifdef emacs
  26. #include "config.h"
  27. #else
  28. #if defined(USG) || defined(STDC_HEADERS)
  29. #define bcopy(s, d, n) memcpy ((d), (s), (n))
  30. #endif
  31. #endif
  32.  
  33. char *getenv ();
  34.  
  35. #ifndef BUFSIZE
  36. #ifdef DEBUG
  37. #define BUFSIZE bufsize
  38.  
  39. int bufsize = 128;
  40. #else
  41. #define BUFSIZE 2048
  42. #endif
  43. #endif
  44.  
  45. #ifndef emacs
  46. static
  47. memory_out ()
  48. {
  49.   write (2, "Virtual memory exhausted\n", 25);
  50.   exit (1);
  51. }
  52.  
  53. static int
  54. xmalloc (size)
  55.      int size;
  56. {
  57.   register tem = malloc (size);
  58.   if (!tem)
  59.     memory_out ();
  60.   return tem;
  61. }
  62.  
  63. static int
  64. xrealloc (ptr, size)
  65.      int ptr;
  66.      int size;
  67. {
  68.   register tem = realloc (ptr, size);
  69.   if (!tem)
  70.     memory_out ();
  71.   return tem;
  72. }
  73. #endif /* not emacs */
  74.  
  75. /* Looking up capabilities in the entry already found */
  76.  
  77. /* The pointer to the data made by tgetent is left here
  78.    for tgetnum, tgetflag and tgetstr to find.  */
  79.  
  80. static char *term_entry;
  81.  
  82. static char *tgetst1 ();
  83.  
  84. /* This is the main subroutine that is used to search
  85.    an entry for a particular capability */
  86.  
  87. static char *
  88. find_capability (bp, cap)
  89.      register char *bp, *cap;
  90. {
  91.   for (; *bp; bp++)
  92.     if (bp[0] == ':'
  93.     && bp[1] == cap[0]
  94.     && bp[2] == cap[1])
  95.       return &bp[4];
  96.   return 0;
  97. }
  98.  
  99. int
  100. tgetnum (cap)
  101.      char *cap;
  102. {
  103.   register char *ptr = find_capability (term_entry, cap);
  104.   if (!ptr || ptr[-1] != '#')
  105.     return -1;
  106.   return atoi (ptr);
  107. }
  108.  
  109. int
  110. tgetflag (cap)
  111.      char *cap;
  112. {
  113.   register char *ptr = find_capability (term_entry, cap);
  114.   return 0 != ptr && ptr[-1] == ':';
  115. }
  116.  
  117. /* Look up a string-valued capability `cap'.
  118.    If `area' is nonzero, it points to a pointer to a block in which
  119.    to store the string.  That pointer is advanced over the space used.
  120.    If `area' is zero, space is allocated with `malloc'.  */
  121.  
  122. char *
  123. tgetstr (cap, area)
  124.      char *cap;
  125.      char **area;
  126. {
  127.   register char *ptr = find_capability (term_entry, cap);
  128.   if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
  129.     return 0;
  130.   return tgetst1 (ptr, area);
  131. }
  132.  
  133. /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
  134.    gives meaning of character following \, or a space if no special meaning.
  135.    Eight characters per line within the string.  */
  136.  
  137. static char esctab[]
  138.   = " \007\010  \033\014 \
  139.       \012 \
  140.   \015 \011 \013 \
  141.         ";
  142.  
  143. /* Given a pointer to a string value inside a termcap entry (`ptr'),
  144.    copy the value and process \ and ^ abbreviations.
  145.    Copy into block that *area points to,
  146.    or to newly allocated storage if area is 0.  */
  147.  
  148. static char *
  149. tgetst1 (ptr, area)
  150.      char *ptr;
  151.      char **area;
  152. {
  153.   register char *p, *r;
  154.   register int c;
  155.   register int size;
  156.   char *ret;
  157.   register int c1;
  158.  
  159.   if (!ptr)
  160.     return 0;
  161.  
  162.   /* `ret' gets address of where to store the string */
  163.   if (!area)
  164.     {
  165.       /* Compute size of block needed (may overestimate) */
  166.       p = ptr;
  167.       while ((c = *p++) && c != ':' && c != '\n');
  168.       ret = (char *) xmalloc (p - ptr + 1);
  169.     }
  170.   else
  171.     ret = *area;
  172.  
  173.   /* Copy the string value, stopping at null or colon.  */
  174.   /* Also process ^ and \ abbreviations.  */
  175.   p = ptr;
  176.   r = ret;
  177.   while ((c = *p++) && c != ':' && c != '\n')
  178.     {
  179.       if (c == '^')
  180.     c = *p++ & 037;
  181.       else if (c == '\\')
  182.     {
  183.       c = *p++;
  184.       if (c >= '0' && c <= '7')
  185.         {
  186.           c -= '0';
  187.           size = 0;
  188.  
  189.           while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
  190.         {
  191.           c *= 8;
  192.           c += c1 - '0';
  193.           p++;
  194.         }
  195.         }
  196.       else if (c >= 0100 && c < 0200)
  197.         {
  198.           c1 = esctab[(c & ~040) - 0100];
  199.           if (c1 != ' ')
  200.         c = c1;
  201.         }
  202.     }
  203.       *r++ = c;
  204.     }
  205.   *r = 0;
  206.   /* Update *area */
  207.   if (area)
  208.     *area = r + 1;
  209.   return ret;
  210. }
  211.  
  212. /* Outputting a string with padding */
  213.  
  214. short ospeed;
  215. /* If OSPEED is 0, we use this as the actual baud rate.  */
  216. int tputs_baud_rate;
  217. char PC;
  218.  
  219. /* Actual baud rate if positive;
  220.    - baud rate / 100 if negative.  */
  221.  
  222. static short speeds[] =
  223.   {
  224. #ifdef VMS
  225.     0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
  226.     -20, -24, -36, -48, -72, -96, -192
  227. #else /* not VMS */
  228.     0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
  229.     -18, -24, -48, -96, -192, -384
  230. #endif /* not VMS */
  231.   };
  232.  
  233. tputs (string, nlines, outfun)
  234.      register char *string;
  235.      int nlines;
  236.      register int (*outfun) ();
  237. {
  238.   register int padcount = 0;
  239.   register int speed;
  240.  
  241. #ifdef emacs
  242.   extern baud_rate;
  243.   speed = baud_rate;
  244. #else
  245.   if (ospeed == 0)
  246.     speed = tputs_baud_rate;
  247.   else
  248.     speed = speeds[ospeed];
  249. #endif
  250.  
  251.   if (string == (char *) 0)
  252.     return;
  253.  
  254.   while (*string >= '0' && *string <= '9')
  255.     {
  256.       padcount += *string++ - '0';
  257.       padcount *= 10;
  258.     }
  259.   if (*string == '.')
  260.     {
  261.       string++;
  262.       padcount += *string++ - '0';
  263.     }
  264.   if (*string == '*')
  265.     {
  266.       string++;
  267.       padcount *= nlines;
  268.     }
  269.   while (*string)
  270.     (*outfun) (*string++);
  271.  
  272.   /* padcount is now in units of tenths of msec.  */
  273.   padcount *= speeds[ospeed];
  274.   padcount += 500;
  275.   padcount /= 1000;
  276.   if (speeds[ospeed] < 0)
  277.     padcount = -padcount;
  278.   else
  279.     {
  280.       padcount += 50;
  281.       padcount /= 100;
  282.     }
  283.  
  284.   while (padcount-- > 0)
  285.     (*outfun) (PC);
  286. }
  287.  
  288. /* Finding the termcap entry in the termcap data base */
  289.  
  290. struct buffer
  291.   {
  292.     char *beg;
  293.     int size;
  294.     char *ptr;
  295.     int ateof;
  296.     int full;
  297.   };
  298.  
  299. /* Forward declarations of static functions */
  300.  
  301. static int scan_file ();
  302. static char *gobble_line ();
  303. static int compare_contin ();
  304. static int name_match ();
  305.  
  306. #ifdef VMS
  307.  
  308. #include <rmsdef.h>
  309. #include <fab.h>
  310. #include <nam.h>
  311.  
  312. static int
  313. legal_filename_p (fn)
  314.      char *fn;
  315. {
  316.   struct FAB fab = cc$rms_fab;
  317.   struct NAM nam = cc$rms_nam;
  318.   char esa[NAM$C_MAXRSS];
  319.  
  320.   fab.fab$l_fna = fn;
  321.   fab.fab$b_fns = strlen(fn);
  322.   fab.fab$l_nam = &nam;
  323.   fab.fab$l_fop = FAB$M_NAM;
  324.  
  325.   nam.nam$l_esa = esa;
  326.   nam.nam$b_ess = sizeof esa;
  327.  
  328.   return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
  329. }
  330.  
  331. #endif /* VMS */
  332.  
  333. /* Find the termcap entry data for terminal type `name'
  334.    and store it in the block that `bp' points to.
  335.    Record its address for future use.
  336.  
  337.    If `bp' is zero, space is dynamically allocated.  */
  338.  
  339. int
  340. tgetent (bp, name)
  341.      char *bp, *name;
  342. {
  343.   register char *tem;
  344.   register int fd;
  345.   struct buffer buf;
  346.   register char *bp1;
  347.   char *bp2;
  348.   char *term;
  349.   int malloc_size = 0;
  350.   register int c;
  351.   char *tcenv;            /* TERMCAP value, if it contais :tc=.  */
  352.   char *indirect = 0;        /* Terminal type in :tc= in TERMCAP value.  */
  353.   int filep;
  354.  
  355.   tem = getenv ("TERMCAP");
  356.   if (tem && *tem == 0) tem = 0;
  357.  
  358. #ifdef VMS
  359.   filep = tem && legal_filename_p (tem);
  360. #else
  361.   filep = tem && (*tem == '/');
  362. #endif /* VMS */
  363.  
  364.   /* If tem is non-null and starts with / (in the un*x case, that is),
  365.      it is a file name to use instead of /etc/termcap.
  366.      If it is non-null and does not start with /,
  367.      it is the entry itself, but only if
  368.      the name the caller requested matches the TERM variable.  */
  369.  
  370.   if (tem && !filep && !strcmp (name, getenv ("TERM")))
  371.     {
  372.       indirect = tgetst1 (find_capability (tem, "tc"), 0);
  373.       if (!indirect)
  374.     {
  375.       if (!bp)
  376.         bp = tem;
  377.       else
  378.         strcpy (bp, tem);
  379.       goto ret;
  380.     }
  381.       else
  382.     {            /* we will need to read /etc/termcap */
  383.       tcenv = tem;
  384.        tem = 0;
  385.     }
  386.     }
  387.   else
  388.     indirect = (char *) 0;
  389.  
  390.   if (!tem)
  391. #ifdef VMS
  392.     tem = "emacs_library:[etc]termcap.d